#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctime>  
#include"bundle.h"
#include<experimental/filesystem>
namespace cloud {
	namespace fs=std::experimental::filesystem;
    class FileUtil {
        private:
            std::string _filename;  // 成员变量名是_filename
        public:
           
            FileUtil(const std::string &filename) : _filename(filename) {}

            // 获取文件大小
            int64_t FileSize() {
                struct stat st;
                if (stat(_filename.c_str(), &st) < 0) {
                    std::cerr << "获取文件大小失败: " << _filename << std::endl;  
                    return -1;
                }
                return st.st_size;
            }

            // 获取最后修改时间
            time_t LastMTime() {
                struct stat st;
                if (stat(_filename.c_str(), &st) < 0) {
                    std::cerr << "获取最后修改时间失败: " << _filename << std::endl;  
                    return 0;  // time_t 用 0 表示错误更合理
                }
                return st.st_mtime;
            }

            // 获取最后访问时间
            time_t LastATime() {
                struct stat st;
                if (stat(_filename.c_str(), &st) < 0) {
                    std::cerr << "获取最后访问时间失败: " << _filename << std::endl;  
                    return 0;
                }
                return st.st_atime;
            }

            // 获取文件名（不含路径）
            std::string FileName() {
                // 处理路径中无 '/' 的情况（如 "test.txt"）
                size_t pos = _filename.find_last_of("/");
                if (pos == std::string::npos) {
                    return _filename;
                }
                // 处理路径以 '/' 结尾的情况（如 "/home/test/"）
                if (pos == _filename.size() - 1) {
                    return "";  // 或根据需求返回默认值
                }
                return _filename.substr(pos + 1);
            }

            
            bool GetPosLen(std::string *body,size_t pos,size_t len) {
				size_t fsize=this->FileSize();
				if(pos+len>fsize)
				{
					std::cout<<"get file len is error!\n";
					return false;
				}
                std::ifstream ifs;
				ifs.open(_filename,std::ios::binary);
				if(ifs.is_open()==false)
				{
					std::cout<<"open failed!\n";
					return false;
				}
				ifs.seekg(pos,std::ios::beg);
				body->resize(len);
				ifs.read(&(*body)[0],len);
				if(ifs.good()==false)
				{
					std::cout<<"get file contest failed!\n";
				}
				ifs.close();
				return true;
            }
			bool GetContent(std::string *body){
				size_t fsize=this->FileSize();
				return GetPosLen(body,0,fsize);
			}
			bool SetContent(const std::string &body){
				std::ofstream ofs;
				ofs.open(_filename,std::ios::binary);
				if(ofs.is_open()==false)
				{
					std::cout<<"write open file failed!\n";
					return false;
				}
				ofs.write(&body[0],body.size());
				if(ofs.good()==false)
				{
					std::cout<<"write file content failed!\n";
					ofs.close();
					return false;
				}
				ofs.close();
				return true;
			}
			bool Compress(const std::string &packname)
			{
				//获取源文件数据
				std::string body;
				if(this->GetContent(&body)==false)
				{
					std::cout<<"compress get file contest failed!\n";
					return false;
				}
				//对数据进行压缩
				std::string packed=bundle::pack(bundle::LZIP,body);
				//将压缩后的数据写入压缩包
				FileUtil fu(packname);
				if(fu.SetContent(packed)==false)
				{
					std::cout<<"compress write packed data failed!\n";
					return false;
				}
				return true;
			}
			bool UnCompress(const std::string &filename)
			{//将压缩包数据读取出来
				std::string body;
				this->GetContent(&body);
				if(this->GetContent(&body)==false)
				{
					std::cout<<"uncompress get file content failed!\n";
					return false;
				}
				//对压缩的数据进行解压缩
				std::string unpacked=bundle::unpack(body);

				//将解压缩的数据写入新文件
				FileUtil fu(filename);
				if(fu.SetContent(unpacked)==false)
				{
					std::cout<<"uncompress write packed data failed!\n";
					return false;
				}
				return true;
			}
			bool Exists()
			{
				return fs::exists(_filename);
			}
			bool CreateDirectory(){
				if(this->Exists())return true;
				return fs::create_directories(_filename);
			}
			bool ScanDirectory(std::vector<std::string> *arry){
				for(auto &p:fs::directory_iterator(_filename))
				{
					if(fs::is_directory(p)==true)
					{
						continue;
					}
					//relative_path 带路径的文件名
					arry->push_back(fs::path(p).relative_path().string());
				}
					return true;
			}
    };
}
